package com.mou.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mou.constant.MessageConstant;
import com.mou.constant.MessageStatus;
import com.mou.context.BaseContext;
import com.mou.dto.ChatBoxDTO;
import com.mou.dto.MessageDTO;
import com.mou.dto.MessageQueryDTO;
import com.mou.entity.ChatBox;
import com.mou.entity.Message;
import com.mou.entity.OnlineUser;
import com.mou.entity.User;
import com.mou.exception.ChatExistException;
import com.mou.mapper.ChatMapper;
import com.mou.mapper.UserMapper;
import com.mou.service.ChatService;
import com.mou.vo.ChatBoxVO;
import com.mou.vo.MessageVO;
import com.mou.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("chatService")
public class ChatServiceImpl extends ServiceImpl<ChatMapper, Message> implements ChatService {
    @Autowired
    private ChatMapper chatMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WebSocketServer webSocketServer;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Integer> sendMessage(MessageDTO messageDTO) {
        // 校验发送者和接收者是否存在
        if (userMapper.selectById(messageDTO.getSenderId()) == null) {
            throw new IllegalArgumentException("发送者不存在");
        }
        if (userMapper.selectById(messageDTO.getReceiverId()) == null) {
            throw new IllegalArgumentException("接受者不存在");
        }

        Message message = new Message();
        message.setSenderId(messageDTO.getSenderId());
        message.setReceiverId(messageDTO.getReceiverId());
        message.setContent(messageDTO.getContent());
        message.setStatus(MessageStatus.PENDING);
        message.setSentTime(LocalDateTime.now());
        ChatBox chatBox = new ChatBox();
        chatBox.setSenderId(messageDTO.getSenderId());
        chatBox.setReceiverId(messageDTO.getReceiverId());
        chatBox.setUpdateTime(LocalDateTime.now());
        chatMapper.updateChatBox(chatBox);
        chatMapper.insert(message);
        List<Integer> userIds = chatMapper.getId(message);

        // 构建WebSocket消息（JSON格式）
        ObjectMapper objectMapper = new ObjectMapper();
        String wsMessage;
        try {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("id", message.getId());
            dataMap.put("content", message.getContent());
            dataMap.put("fromUserId", message.getSenderId());
            dataMap.put("timestamp", LocalDateTime.now().toString());

            Map<String, Object> rootMap = new HashMap<>();
            rootMap.put("type", "NEW_MESSAGE");
            rootMap.put("data", dataMap);

            wsMessage = objectMapper.writeValueAsString(rootMap);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("消息序列化失败", e);
        }


        // 发送WebSocket消息
        WebSocketServer.sendMessageToUser(
                messageDTO.getReceiverId().toString(),
                wsMessage
        );
        return userIds;
    }

    @Override
    public List<MessageVO> getMessages(MessageQueryDTO messageQueryDTO) {
        messageQueryDTO.setSenderId(BaseContext.getCurrentId());
        List<MessageVO> messages = chatMapper.getMessages(messageQueryDTO);
        return messages;
    }

    @Override
    public void markMessageAsRead(Integer id) {
        Integer currentId = BaseContext.getCurrentId();
        chatMapper.markMessageAsRead(currentId,id);
    }

    @Override
    public List<ChatBoxVO> getChatBox() {
        Integer currentId = BaseContext.getCurrentId();
        List<ChatBox> chatBoxes = chatMapper.getChatBox(currentId);
        List<ChatBoxVO> chatBoxVOS = new ArrayList<>();
        for (ChatBox chatBox : chatBoxes) {
            ChatBoxVO chatBoxVO = new ChatBoxVO();
            User user = userMapper.selectById(chatBox.getReceiverId());
            if (user != null) {
                chatBoxVO.setId(chatBox.getId());
                chatBoxVO.setNickname(user.getNickname());
                chatBoxVO.setAvatar(user.getAvatar());
                chatBoxVO.setReceiverId(chatBox.getReceiverId());
                Integer unReadMessageCount = chatMapper.getUnReadMessageCount(currentId, chatBox.getReceiverId());
                OnlineUser onlineUser = userMapper.getOnlineUserById(user.getId());
                chatBoxVO.setIsOnline(onlineUser.getIsOnline());
                chatBoxVO.setUnRead(unReadMessageCount);
                chatBoxVOS.add(chatBoxVO);
            }
        }
        return chatBoxVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addChatBox(ChatBoxDTO chatBoxDTO) {
        Integer exists = chatMapper.existsChatBox(chatBoxDTO);
        if (exists == 0) {
            ChatBox chatBox = new ChatBox();
            chatBox.setSenderId(chatBoxDTO.getSenderId());
            chatBox.setReceiverId(chatBoxDTO.getReceiverId());
            chatBox.setCreateTime(LocalDateTime.now());
            chatBox.setUpdateTime(LocalDateTime.now());
            chatMapper.addChatBox(chatBox);
            ChatBox chatBox2 = new ChatBox();
            chatBox2.setSenderId(chatBoxDTO.getReceiverId());
            chatBox2.setReceiverId(chatBoxDTO.getSenderId());
            chatBox2.setCreateTime(LocalDateTime.now());
            chatBox2.setUpdateTime(LocalDateTime.now());
            chatMapper.addChatBox(chatBox2);
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("receiverId", chatBox.getReceiverId());
            dataMap.put("senderId", chatBox.getSenderId());
            dataMap.put("timestamp", LocalDateTime.now().toString());

            Map<String, Object> messageMap = new HashMap<>();
            messageMap.put("type", "NEW_CHAT");
            messageMap.put("data", dataMap);

            WebSocketServer.broadcast(messageMap.toString());
        } else {
            throw new ChatExistException(MessageConstant.CHAT_EXIST);
        }
    }
}
